/*
 * Lib.cpp
 *
 *  Created on: May 27, 2009
 *      Author: ruslan
 */

#include "Lib.h"
#include <list>
#include <string>
#include <sstream>
#include <iostream>
#include <sys/time.h>

using namespace std;

 string Lib::htmlRepresentOfSchedule(int*** cubSchedule,int m, int n, int l, list<int*> errorList, string topText = "", string bottomText = "") {
	string html = "<html><title>Sulution of SGP</title><style type=\"text/css\">table{display:inline-table;margin:8px;} td.error{background-color:red;}</style><body><h1>Solution of Social Golfer Problem</h1>";
	html.append(topText);
	list<int*>::iterator iterInErrorList = errorList.begin();
	for (int i=0; i<m; i++) {
		html.append("<table border=\"1px\">");
		for (int j=0; j<n; j++) {
			html.append("<tr>");
			for (int k=0; k<l; k++) {
				html.append("<td");
				if (iterInErrorList != errorList.end() ) {
					int* tmp = (*iterInErrorList);
					if (tmp[0] == i && tmp[1] == j && tmp[2] == k) {
						html.append(" class=\"error\"");
						iterInErrorList++;
					}
				}
				html.append(">");
				std::stringstream out;
				out << cubSchedule[i][j][k];
				html += out.str();
				html.append("</td>");
			}
			html.append("</tr>");

		}
		html.append("</table>");
	}
	html.append(bottomText);
	html.append("</body></html>");
	return html;
}

 list<int*> Lib::checkSchedule (int*** cubSchedule, int m, int n, int l, int i, int j, int k) {
 		list<int*> errorList = list<int*>();
 		//int maxWeeks = m;
 		int maxGroups = n;
 		int maxPlayersInGroup = l;
 		int playersCnt = maxGroups*maxPlayersInGroup;
 		bool* arrFreePlayersInWeek = new bool[playersCnt];
 		bool** mtrxFreeCouples = new bool*[playersCnt];

		for (int i2=0; i2<playersCnt; i2++) {
			arrFreePlayersInWeek[i2] = true;
			mtrxFreeCouples[i2] = new bool [playersCnt];
			for (int j2=0; j2<playersCnt; j2++) {
				if (i2==j2)
					mtrxFreeCouples[i2][j2] = false; // isn't allowed
				else
					mtrxFreeCouples[i2][j2] = true; // allowed
			}
		}
 		bool* errorMarker = new bool[maxPlayersInGroup];
 		for (int i2=0; i2<=i; i2++) {
 			for (int j2=0; ((i2<i)&&(j2<maxGroups)) || ((i2==i)&&(j2<=j)); j2++) {
 				int k2=0;
 				for (; (((i2<i)||((i2==i)&&(j2<j)))&&(k2<maxPlayersInGroup)) || ((i2==i)&&(j2==j)&&(k2<=k)); k2++) {

 					int currPlayer = cubSchedule[i2][j2][k2];
 					if (currPlayer>=0) {
 						if (arrFreePlayersInWeek[currPlayer]) {
 							arrFreePlayersInWeek[currPlayer] = false;
 							errorMarker[k2] = false; // all right
 						}
 						else
 							errorMarker[k2] = true; // problems
 						for (int l2=0; l2<k2 ;l2++) {
 							int tmpPlayer = cubSchedule[i2][j2][l2];
 							if (mtrxFreeCouples[currPlayer][tmpPlayer]) {
 								mtrxFreeCouples[currPlayer][tmpPlayer] = false;
 								mtrxFreeCouples[tmpPlayer][currPlayer] = false;
 							}
 							else {
 								errorMarker[k2] = true; // problems
 								errorMarker[l2] = true; // problems
 							}
 						}
 					}
 					else
 						errorMarker[k2] = true; // problems
 				}
 				for (int m2=0; m2<k2; m2++) {
 					if (errorMarker[m2] == true) {
 						int* tmpErr = new int[3];
 						tmpErr[0] = i2;
 						tmpErr[1] = j2;
 						tmpErr[2] = m2;
 						errorList.push_back(tmpErr);
 					}
 				}

 			}
 			for (int i1=0; i1<playersCnt;i1++) {
 				arrFreePlayersInWeek[i1] = true;
 			}
 		}
 		delete [] arrFreePlayersInWeek;

 		Lib::deleteMatrix(mtrxFreeCouples, playersCnt);

 		return errorList;
 }

 long Lib::getTimeDiffInMilliseconds (timeval start, timeval end) {
	 long seconds, useconds, timeInMs;
	 seconds  = end.tv_sec  - start.tv_sec;
	 useconds = end.tv_usec - start.tv_usec;
	 timeInMs = ((seconds) * 1000 + useconds/1000);
	 return timeInMs;
 }


 string Lib::formatTimeInMilliseconds(long timeInMs) {
	long days = timeInMs / (1000*60*60*24);
	long hours = timeInMs / (1000*60*60) % 24;
	long minutes = timeInMs / (1000*60) % 60;
	long sec = timeInMs / (1000) % 60;
	long ms = timeInMs % 1000;

	string strTime;
	if (days>0) {
		std::stringstream out;
		out << days;
		strTime += out.str();
		strTime.append("d ");
	}
	if (hours>0) {
		std::stringstream out;
		out << hours;
		strTime += out.str();
		strTime.append("h ");
	}
	if (minutes>0) {
		std::stringstream out;
		out << minutes;
		strTime += out.str();
		strTime.append("m ");
	}
	if (sec>0) {
		std::stringstream out;
		out << sec;
		strTime += out.str();
		strTime.append("s ");
	}
	{
		std::stringstream out;
		out << ms;
		strTime += out.str();
	}
	strTime.append("ms");

	return strTime;
}

 void Lib::getTimeDiffInMilliseconds(string& strDifFromStart, string& strDifFromPrevTS, bool reset = false) {
	 static bool wasInit = false;
	 static timeval tsStart, tsPrevTimestamp;//, tsCurTimestamp;
	 if (!wasInit || reset) {
		 gettimeofday(&tsStart, NULL);
		 tsPrevTimestamp = tsStart;
		 strDifFromStart = formatTimeInMilliseconds(0);
		 strDifFromPrevTS = strDifFromStart;
		 wasInit = true;
	 }
	 else {
		 timeval tsCurTimestamp;
		 long timeDifFromStart, timeDifFromPrev;
		 gettimeofday(&tsCurTimestamp, NULL);
		 timeDifFromStart = getTimeDiffInMilliseconds(tsStart, tsCurTimestamp);
		 strDifFromStart = formatTimeInMilliseconds(timeDifFromStart);
		 timeDifFromPrev = getTimeDiffInMilliseconds(tsPrevTimestamp, tsCurTimestamp);
		 strDifFromPrevTS = formatTimeInMilliseconds(timeDifFromPrev);
//cout << tsStart.tv_sec<<endl;
		 tsPrevTimestamp = tsCurTimestamp;
	 }
 }

 void Lib::deleteValueofPointersToArrInList(list<int*> l) {
	 list<int*>::iterator iter = l.begin();
	 while (iter != l.end()) {
		 delete [] (*iter);
		 iter++;
	 }
 }

string Lib::getMtrx3AsString(string name, int*** mtrx3, int n, int m, int l) {
	std::stringstream out;
	out<<name<<" = "<<endl;
	 for (int i=0; i<n; i++) {
		 for (int j=0; j<m; j++) {
			 for (int k=0; k<l; k++)
				 out<<" "<<mtrx3[i][j][k];
			 out<<endl;
		 }
		 out<<endl;
	 }
	 out<<endl;
	 return out.str();
 }

string Lib::getMtrxGamesAsString(int** mtrxGames, int playersCnt) {
	std::stringstream out;
	out<<"mtrxGames = "<<endl;
	for (int i=0; i<playersCnt; i++) {
		for (int j=0; j<playersCnt; j++)
			out<<" "<<mtrxGames[i][j];
		out<<endl;
	}
	out<<endl;
	return out.str();
}
string Lib::getMtrx4TabuAsString(int**** mtrx4Tabu, int WEEKS, int playersCnt) {
	std::stringstream out;
	out<<"mtrx4Tabu = "<<endl;
	for (int i=0; i<WEEKS; i++) {
		for (int j=0; j<playersCnt; j++) {
				for (int k=0; k<playersCnt; k++)
					if (j!=k)
						out<<" "<<mtrx4Tabu[i][j][k][0]<<";"<<mtrx4Tabu[i][j][k][1];
					else
						out<<" --;--";
				out<<endl;
			}
		out<<endl;
	}
	out<<endl;
	return out.str();
}
string Lib::getMtrxConflictIndecesAsString(list<int>** arrConflictIndeces, int WEEKS, int GROUPS_IN_WEEK) {
	std::stringstream out;
	out<<"arrConflictIndeces = "<<endl;
	 for (int i=0; i<WEEKS; i++) {
		 for (int j=0; j<GROUPS_IN_WEEK; j++) {
			 list<int>::iterator iter = arrConflictIndeces[i][j].begin();
			 while (iter != arrConflictIndeces[i][j].end()) {
				 out<<" "<<(*iter);
				 iter++;
			 }
			 out<<endl;
		 }
		 out<<endl;
	 }
	 out<<endl;
	 return out.str();
}


